package com.cd.university.service.impl;

import com.cd.university.common.UniversityConstants;
import com.cd.university.controller.form.RolePermissionForm;
import com.cd.university.db.mapper.PermissionMapper;
import com.cd.university.db.mapper.RolePermissionMapper;
import com.cd.university.db.pojo.Permission;
import com.cd.university.db.pojo.RolePermission;
import com.cd.university.service.PermissionService;
import com.cd.university.vo.PermissionVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * @author 陈栋
 * @create 2021/9/20 19:06
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class PermissionServiceImpl implements PermissionService {

    /**
     * 从数据库中查询的所有权限
     */
    private volatile List<Permission> permissions;

    /**
     * 根据数据库中得到的所有权限封装成传给controller的权限列表集合
     */
    private List<PermissionVo> permissionVoList;

    @Autowired
    private PermissionMapper permissionMapper;

    @Autowired
    private RolePermissionMapper rolePermissionMapper;

    private List<RolePermission> rolePermissionList;

    @Override
    public void insertPermission(List<RolePermissionForm> list) {
        if (list.size()==0) {
            throw new RuntimeException("插入列表为空");
        }
        List<RolePermission> rolePermissionList = new ArrayList<>();
        getPermissionVoList();


        for (RolePermissionForm form : list) {
            rolePermissionList.add(new RolePermission(form.getRoleId(), form.getPermissionId()));
        }

        // 向role_permission表里面插入角色
        rolePermissionMapper.insertPermissionId(rolePermissionList);
    }

    @Override
    public List<PermissionVo> searchAllPermissionVo() {
        return getPermissionVoList();
    }

    @Override
    public List<PermissionVo> searchPermissionByRoleId(Integer roleId) {
        // TODO: 2021/9/21 这里只是简单的返回权限id对应的权限列表
        // 如果还没有查询，则进行初始化
        getPermissionVoList();
        ArrayList<PermissionVo> result = new ArrayList<>();

        List<RolePermission> rolePermissionList = searchRolePermissionListByRoleId(roleId);

        if (rolePermissionList ==null) {
            throw new RuntimeException("不存在该角色id，请检查");
        }

        for (RolePermission rolePermission : rolePermissionList) {

            for (Permission permission : permissions) {
                if (permission.getPermissionId().equals(rolePermission.getPermissionId())) {
                    result.add(permissionToPermissionTestVo(permission));
                    break;
                }
            }
        }
        return result;
    }

    @Override
    public void deletePermissionId(List<RolePermissionForm> list) {
        if (list.size()==0) {
            throw new RuntimeException("删除集合不能为空");
        }
        // 获得要删除的列表的角色id
        Integer roleId = list.get(0).getRoleId();

        // 遍历得到权限idSet集合
        Set<Integer> permissionIdSet = new HashSet<>();
        for (RolePermissionForm rolePermissionForm : list) {
            permissionIdSet.add(rolePermissionForm.getPermissionId());
        }

        HashMap<String ,Object> param = new HashMap<>();
        param.put("roleId",roleId);
        param.put("permissionIdSet", permissionIdSet);
        rolePermissionMapper.deletePermissionId(param);
    }

    @Override
    public List<PermissionVo> searchPermissionLeafByRoleId(Integer roleId) {
        // 如果还没有查询，则进行初始化
        getPermissionVoList();
        ArrayList<PermissionVo> result = new ArrayList<>();

        List<RolePermission> rolePermissionList = searchRolePermissionListByRoleId(roleId);

        if (rolePermissionList ==null) {
            throw new NullPointerException("角色id没有权限,或者角色不存在");
        }

        // 取出权限树中每一个节点，存在PermissionVo数组中
        PermissionVo[] allPermissionVo = new PermissionVo[permissions.size()+10];
        getAllPermissionVoList(allPermissionVo, permissionVoList);


        // 遍历角色的所有的权限，找出权限树中对应的所有的节点，把叶子加入到result集合中
        for (RolePermission rolePermission : rolePermissionList) {
            // 保险防止数据不存在，发生空指针异常
            if (allPermissionVo[rolePermission.getPermissionId()]!=null) {
                // 如果没有子节点
                if (allPermissionVo[rolePermission.getPermissionId()].getSonPermissions()==null) {
                    result.add(allPermissionVo[rolePermission.getPermissionId()]);
                }
            }
        }

        return result;

    }


    /**
     * 懒加载
     * 获所有的权限，并且封装成PermissionVo
     * 关键是每一个权限里面都有了子权限
     * @return 权限Vo集合
     */
    private List<PermissionVo> getPermissionVoList() {
        // 如果已经进行了初始化，那么直接返回
        if (permissionVoList!=null && permissionVoList .size() > 0) {
            return permissionVoList;
        }
        // 如果还没有进行初始化
        permissionVoList = new ArrayList<>();
        permissions = permissionMapper.searchPermissionByOpen();

        // 先查询根目录
        for (Permission permission : permissions) {
            // 如果是根权限Id，那么直接在这里添加
            if (permission.getPermissionPid().equals(UniversityConstants.ROOT_PARENT_ID)) {
                permissionVoList.add(permissionToPermissionTestVo(permission));
            }
        }

        findSonPermission(permissionVoList, permissions);
        return permissionVoList;
    }

    /**
     * 递归查询子权限
     * @param permissionVoList 权限的VO集合
     * @param permissions 所有的权限
     */
    private List<PermissionVo> findSonPermission(List<PermissionVo> permissionVoList,
                                                 List<Permission> permissions) {
        for (PermissionVo permissionVo : permissionVoList) {
            // 创建一个子权限列表
            List<PermissionVo> sonPermissionVoList = new ArrayList<>();

            // 遍历所有的权限，如果发现权限的pid与当前的id相同，那么说明遍历得到的权限是子权限
            for (Permission permission : permissions) {
                if (permissionVo.getPermissionId().equals(permission.getPermissionPid())) {
                    PermissionVo sonVo = permissionToPermissionTestVo(permission);
                    sonPermissionVoList.add(sonVo);
                }

                // 如果子权限列表不为空，那么重新为父权限设置子权限列表
                if (sonPermissionVoList.size() > 0) {
                    permissionVo.setSonPermissions(sonPermissionVoList);
                }

                // 递归进行
                findSonPermission(sonPermissionVoList,permissions);
            }
        }
        return permissionVoList;
    }


    /**
     * 递归查询一个权限id下面的所有子权限id
     * @param permissionIdSet 权限集合
     * @param permissionId 父权限Id
     * @return
     */
    private Set<Integer> findSonPermissionId(Set<Integer> permissionIdSet,
                                             int permissionId) {
        permissionIdSet.add(permissionId);
        for (Permission permission : permissions) {
            if (permission.getPermissionPid().equals(permissionId)) {
                findSonPermissionId(permissionIdSet,permission.getPermissionId());
            }
        }
        return permissionIdSet;
    }

    /**
     * Permission的pojo转成Permission的Vo对象
     * @param permission pojo实列
     * @return Vo对象
     */
    private PermissionVo permissionToPermissionTestVo(Permission permission) {
        // 创建一个vo对象
        PermissionVo vo = new PermissionVo();
        // 把数据库中遍历到的Permission的pojo对象拷贝到PermissionVo中
        BeanUtils.copyProperties(permission,vo);
        return vo;
    }

    /**
     * 取得权限树中的所有的节点
     * @param permissionVoList 权限树
     * @return 权限树中所有的节点
     */
    private void getAllPermissionVoList(PermissionVo[] allPermission,
                                        List<PermissionVo> permissionVoList) {

        if (permissionVoList==null) {
            return;
        }

        for (PermissionVo permissionVo : permissionVoList) {
            allPermission[permissionVo.getPermissionId()] = permissionVo;
            getAllPermissionVoList(allPermission,permissionVo.getSonPermissions());
        }
    }

    @Async
    public void updateRolePermissionListToCache() {
        rolePermissionList = rolePermissionMapper.searchAllRoleAndPermission();
    }

    /**
     * 通过角色id查询所有的权限角色id
     * @param roleId 角色id
     * @return 角色权限集合
     */
    public List<RolePermission> searchRolePermissionListByRoleId(Integer roleId) {
        // 如果第一次加载
        if (rolePermissionList==null) {
            updateRolePermissionListToCache();
        }
        ArrayList<RolePermission> list = new ArrayList<>();

        // 根据角色id查询所有的权限角色id
        for (RolePermission rolePermission : rolePermissionList) {
            if (rolePermission.getRoleId().equals(roleId)) {
                list.add(rolePermission);
            }
        }

        return list;
    }

}
